package controllers

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"gitee.com/yizhongi/wfw/models"
	"gitee.com/yizhongi/wfw/util"
	"github.com/beego/beego/v2/adapter/orm"
	"github.com/beego/beego/v2/core/logs"
)

type TaskApiController struct {
	BaseController
}

// @Title getTasks
// @Description get all the tasks
// @Param   page           query   int      false       "页数"
// @Param   limit          query   int      false        "每页数目"
// @Success 0 {object} models.DeployTask
// @router /list
func (this *TaskApiController) ListTasks() {
	limit, err_1 := this.GetInt("limit")
	page, err_2 := this.GetInt("page")
	if err_1 != nil && err_2 != nil {
		this.ErrorJson(500, err_1.Error()+err_2.Error(), nil)
	}
	var tasks []*models.DeployTask

	o := orm.NewOrm()
	deployTask := new(models.DeployTask)
	qs := o.QueryTable(deployTask)
	cnt, err := qs.Count()
	if err != nil {
		this.ErrorJson(500, err.Error(), nil)
	}
	qs.Limit(limit, (page-1)*limit)
	num, err := qs.All(&tasks)
	fmt.Printf("Returned Rows Num: %v, %v", num, err)
	if err != nil {
		this.ErrorJson(500, err.Error(), nil)
	}
	this.LayuiSuccessJson(cnt, tasks)
}

// @Title AddTask
// @添加一个任务
// @Param   page           query   int      false       "页数"
// @Param   limit          query   int      false        "每页数目"
// @Success 0 {object} models.DeployTask
// @router /add [post]
func (c *TaskApiController) AddTask() {
	o := orm.NewOrm()
	t := models.DeployTask{}
	if err := c.ParseForm(&t); err != nil {
		fmt.Println(err)
	} else {
		CheckStore(&t)
		_, err := o.Insert(&t)
		if err != nil {
			panic("insert err:" + err.Error())
		}
		SavePortAndVolume(c, &t)
		if err == nil {
			c.SuccessJson("保存成功", t.ID)
		}

	}
}

// @Title AddTask
// @添加一个任务
// @Param   page           query   int      false       "页数"
// @Param   limit          query   int      false        "每页数目"
// @Success 0 {object} models.DeployTask
// @router /edit [post]
func (c *TaskApiController) Edit() {
	o := orm.NewOrm()
	t := models.DeployTask{}
	if err := c.ParseForm(&t); err != nil {
		fmt.Println(err)
	} else {
		dst := models.DeployTask{ID: t.ID}
		o.Read(&dst)
		util.CopyStructValue(t, &dst)
		CheckStore(&dst)
		_, err := o.Update(&dst)
		if err != nil {
			panic("insert err:" + err.Error())
		}
		//先删除关联数据，再新建
		i, e1 := o.QueryTable(&models.Port{}).Filter("DeployTask", dst.ID).Delete()
		i2, e2 := o.QueryTable(&models.Volume{}).Filter("DeployTask", dst.ID).Delete()
		fmt.Printf("%v:%v", i, e1)
		fmt.Printf("%v:%v", i2, e2)
		SavePortAndVolume(c, &dst)
		if err == nil {
			c.SuccessJson("保存成功", dst.ID)
		}

	}
}

func SavePortAndVolume(c *TaskApiController, t *models.DeployTask) {
	o := orm.NewOrm()
	lport := make([]int, 0, 5)
	cport := make([]int, 0, 5)
	lvolume := make([]string, 0, 5)
	cvolume := make([]string, 0, 5)
	c.Ctx.Input.Bind(&lport, "lPort")
	c.Ctx.Input.Bind(&cport, "cPort")
	c.Ctx.Input.Bind(&lvolume, "lVolume")
	c.Ctx.Input.Bind(&cvolume, "cVolume")
	for i, v := range lport {
		if v > 0 && v < 65536 {
			if v2 := cport[i]; v2 > 0 && v2 < 65536 {
				p := &models.Port{Local: v, Container: cport[i]}
				p.DeployTask = t
				o.Insert(p)
			} else if v2 != 0 {
				c.ErrorJson(500, "端口号取值1-65535", nil)
			}
		} else if v != 0 {
			c.ErrorJson(500, "端口号取值1-65535", nil)
		}
	}
	for i, v := range lvolume {
		if v != "" && cvolume[i] != "" {
			v := &models.Volume{Local: v, Container: cvolume[i]}
			v.DeployTask = t
			o.Insert(v)
		}
	}
}

// @Title AddTask
// @添加一个任务
// @Param   page           query   int      false       "页数"
// @Param   limit          query   int      false        "每页数目"
// @Success 0 {object} models.DeployTask
// @router /del/?:id [delete]
func (c *TaskApiController) Delete() {
	tid, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
	o := orm.NewOrm()
	if _, err := o.Delete(&models.DeployTask{ID: tid}); err == nil {
		c.SuccessJson("删除成功", nil)
	} else {
		c.Abort("503")
	}
}

func CheckStore(task *models.DeployTask) {
	if task.ImageName != "" {
		addr := strings.Split(task.ImageName, "/")[0]
		o := orm.NewOrm()
		var store models.Store
		err := o.QueryTable("store").Filter("addr", addr).One(&store)
		if err == nil {
			task.Store = &store
		}
	}
}

//Deploy 部署任务 tid为任务id号，v为镜像版本号 api/task/deploy?tid=&v=
// @router /deploy [get]
func (c *TaskApiController) Deploy() {
	var tid int
	c.Ctx.Input.Bind(&tid, "tid") //id ==123
	var version string
	c.Ctx.Input.Bind(&version, "v")
	//tid := c.Ctx.Input.Param(":task_id")
	//intTid, _ := strconv.Atoi(tid)
	logs.Debug(tid)
	//1. read task info
	o := orm.NewOrm()
	task := models.DeployTask{ID: tid}
	o.Read(&task)
	// if err == orm.ErrNoRows {
	// 	fmt.Println("查询不到")
	// } else if err == orm.ErrMissPK {
	// 	fmt.Println("找不到主键")
	// } else {
	// 	fmt.Println(task.Id, task.Name)
	// }
	//2.pull image
	crc := util.NewContainerRuntimeAPIClient()
	var imageID string
	if task.Store != nil {
		o.Read(task.Store)
		imageID = crc.ImagePullByAuth(task.ImageName, version, task.Store.UserName, task.Store.Password)
	}

	//2.1 重命名正在执行的镜像名称

	//3.stop and remove contanier
	if task.ContainerID != "" {
		crc.ContainerStopAndRemove(task.ContainerID)
	}
	var ports map[string]string
	var volumes map[string]string
	if _, err := o.LoadRelated(&task, "Port"); err != nil {
		ports = make(map[string]string)
		for _, p := range task.Port {
			ports[string(rune(p.Container))] = string(rune(p.Local))
		}
	}
	if _, err := o.LoadRelated(&task, "Volume"); err != nil {
		volumes = make(map[string]string)
		for _, v := range task.Volume {
			volumes[v.Container] = v.Local
		}
	}
	//4.start contanier
	containerOption := &util.ContainerOption{
		ImageName:     task.ContainerID,
		ContainerName: task.ContainerName,
		PublishPorts:  ports,
		Volume:        volumes,
	}
	cid := crc.ContainerStart(containerOption)
	task.ContainerID = cid
	task.TaskState = true
	if num, err := o.Update(&task); err == nil {
		fmt.Println(num)
	}
	taskRunEvent := &models.TaskRun{
		Task:         &task,
		ImageVersion: GetCurrentVersion(),
		ImageID:      imageID,
		ContainerID:  cid,
		IsSuccess:    cid != "",
	}
	o.Insert(&taskRunEvent)
}

//GetCurrentVersion
func GetCurrentVersion() string {
	return time.Now().Format("06.01.02.15.04")
}

//GetWebHookAddr 获取webHook地址
//
// @router /hook/?:taskID [get]
func (c *TaskApiController) GetWebHookAddr() string {
	tid, _ := strconv.Atoi(c.Ctx.Input.Param(":taskID"))
	o := orm.NewOrm()
	task := models.DeployTask{ID: tid}
	o.Read(&task)
	// http://ip(domain):port/api/task/d?t=&id=&v=

	return ""
}
